﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using dotNetMembership = System.Web.Security.Membership;
using dotNetRoles = System.Web.Security.Roles;
using Binding = System.Web.Mvc.BindingHelperExtensions;
using StarterKits.Mvc.Filters.FormsAuthentication;
using StarterKits.Mvc.Membership.Controllers;
using P.InOut.NetMvc.Logging;
using P.InOut.NetMvc.Properties;
using P.InOut.NetMvc.Common;
using P.InOut.NetMvc.Models;

namespace P.InOut.NetMvc.Controllers
{
    public class JsonUpdates
    {
        public int Status { get; set; }

        public long Queried { get; set; }

        public object Updates { get; set; }
    }

    public class UpdatesServiceController : InOutServiceController
    {
        private InOutDatabaseLogger logger = new InOutDatabaseLogger();

        public UpdatesServiceController()
        {
            ViewData["ErrorMessage"] = string.Empty;
        }

        [RequiresAuthentication()]
        public override JsonResult Get()
        {
            // Get User
            MembershipUser user = Membership.GetUser(this.User.Identity.Name);

            // Open Data Context
            InOutDataContext db = new InOutDataContext(Settings.Default.dbConn);

            // Get list of teams user is a member of
            List<Team> memberOf = (from t in db.MemberTeams
                                   where t.UserId == (Guid)user.ProviderUserKey
                                   select t.Team).ToList<Team>();

            List<Guid> teamMembers = (from t in db.MemberTeams
                                      where memberOf.Contains(t.Team)
                                      select t.UserId).ToList<Guid>();

            string partialTime = this.Request.Params["lastPartial"];
            if (partialTime == null)
            {
                // Get list of updates for members in the same teams as user
                var updates = (from u in db.Updates
                               where teamMembers.Contains(u.UserId) && u.Active == true
                               orderby u.DateTimeEntered
                               select new
                               {
                                   Id = u.Id,
                                   DateTimeEntered = u.DateTimeEntered,
                                   UserId = u.UserId,
                                   UserName = HttpUtility.HtmlEncode(u.Aspnet_Membership.Aspnet_User.UserName),
                                   UpdateText = HttpUtility.HtmlEncode(u.UpdateText)
                               });

                JsonUpdates jsonUpdates = new JsonUpdates
                {
                    Status = 200,
                    Queried = DateTime.Now.Ticks,
                    Updates = updates
                };

                return this.Json(jsonUpdates);

            } else {
                long lastRequest = long.Parse(partialTime);

                // Get list of updates for members in the same teams as user
                var updates = (from u in db.UpdateActivities
                               orderby u.Update.DateTimeEntered
                               where teamMembers.Contains(u.UserId)  
                                    && u.DateTimeActivity > lastRequest
                               select new
                               {
                                   Id = u.Update.Id,
                                   Activity = u.Activity,
                                   DateTimeEntered = u.Update.DateTimeEntered,
                                   UserId = u.UserId,
                                   UserName = HttpUtility.HtmlEncode(u.Aspnet_Membership.Aspnet_User.UserName),
                                   UpdateText = HttpUtility.HtmlEncode(u.Update.UpdateText)
                               });

                JsonUpdates jsonUpdates = new JsonUpdates
                {
                    Status = 200,
                    Queried = DateTime.Now.Ticks,
                    Updates = updates
                };                

                return this.Json(jsonUpdates);
            }
        }

        [RequiresAuthentication()]
        public override JsonResult Detail(object id)
        {
            return this.Json(RedirectToAction("Index", "UpdatesService"));
        }

        [NonAction]
        public virtual void OnBeforeCreate() { }

        [NonAction]
        public virtual void OnAfterCreate() { }

        [RequiresAuthentication()]
        public override JsonResult Create()
        {
            using (InOutDataContext db =
                new InOutDataContext(Settings.Default.dbConn))
            {
                // Get current user
                MembershipUser user = Membership.GetUser();

                OnBeforeCreate();

                // Create new Update and set Properties
                Update update = new Update
                {
                    Active          = true,
                    UserId          = (Guid)user.ProviderUserKey,
                    DateTimeEntered = DateTime.Now,
                    UpdateText      = Request.Form["UpdateText"]
                };

                // Insert and Submit Changes to the db
                db.Updates.InsertOnSubmit(update);
                db.SubmitChanges();

                // Create new UpdateActivity and set properties
                UpdateActivity activity = new UpdateActivity
                {
                    Activity            = "Insert",
                    DateTimeActivity    = DateTime.Now.Ticks,
                    UpdateId            = update.Id,
                    UserId              = (Guid)user.ProviderUserKey
                };

                // Insert and Submit Changes to the db
                db.UpdateActivities.InsertOnSubmit(activity);
                db.SubmitChanges();

                OnAfterCreate();

                return this.Json(new JsonUpdates { Status = 200 });
            }
        }

        [NonAction]
        public virtual void OnBeforeUpdate(object id) { }

        [NonAction]
        public virtual void OnAfterUpdate(object id) { }

        [RequiresAuthentication]
        public override JsonResult Update(object id)
        {
            using (InOutDataContext db =
                new InOutDataContext(Settings.Default.dbConn))
            {
                Update update = db.Updates.Single<Update>(u => u.Id == int.Parse(id.ToString()));

                MembershipUser user = dotNetMembership.GetUser();
                if ((Guid)user.ProviderUserKey == update.UserId)
                {
                    update.UpdateText = Request.Form["UpdateText"];

                    OnBeforeUpdate(id);

                    // Create new UpdateActivity and set properties
                    UpdateActivity activity = new UpdateActivity
                    {
                        Activity            = "Update",
                        DateTimeActivity    = DateTime.Now.Ticks,
                        UpdateId            = update.Id,
                        UserId              = (Guid)user.ProviderUserKey
                    };

                    // Insert and Submit Changes to the db
                    db.UpdateActivities.InsertOnSubmit(activity);
                    db.SubmitChanges();



                    OnAfterUpdate(id);
                }

                return this.Json(new JsonUpdates { Status = 200 });
            }
        }

        [NonAction]
        public virtual void OnBeforeDelete(object id) { }

        [NonAction]
        public virtual void OnAfterDelete(object id) { }

        [RequiresAuthentication]
        public override JsonResult Delete(object id)
        {
            using (InOutDataContext db =
                new InOutDataContext(Settings.Default.dbConn))
            {
                Update update = db.Updates.Single<Update>(u => u.Id == int.Parse(id.ToString()));

                MembershipUser user = dotNetMembership.GetUser();
                if ((Guid)user.ProviderUserKey == update.UserId)
                {
                    // Delete update
                    update.Active = false;

                    // Create new UpdateActivity and set properties
                    UpdateActivity activity = new UpdateActivity
                    {
                        Activity            = "Delete",
                        DateTimeActivity    = DateTime.Now.Ticks,
                        UpdateId            = update.Id,
                        UserId              = (Guid)user.ProviderUserKey
                    };

                    // Insert and Submit Changes to the db
                    db.UpdateActivities.InsertOnSubmit(activity);
                    db.SubmitChanges();
                }

                return this.Json(new JsonUpdates { Status = 200 });
            }
        }
    }
}
